Skip to content

Conversation

@RalfJung
Copy link
Member

Also, mention the .for_each(drop) pattern in the documentation. One can't always use retain with a negated predicate as that does not have a range argument.

r? @the8472

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Nov 16, 2025
Copy link
Member

@the8472 the8472 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nicer if we had map.range_mut(..).discard() and similar range operations. But until then extract_if is the best we offer... ok.

View changes since this review

/// assert_eq!(high.keys().copied().collect::<Vec<_>>(), [4, 5, 6, 7]);
/// ```
#[stable(feature = "btree_extract_if", since = "1.91.0")]
#[must_use = "use `extract_if().for_each(drop)` to remove all extracted elements"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording we have on most iterators is simply

#[must_use = "iterators are lazy and do nothing unless consumed"]

It's possible that the user meant to use the iterator results but forgot to somehow.

for_each(drop) is only recommended by an unused collect()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The drain iterator is also lazy and still does something when not consumed... so if the user knows drain, which is likely, then just talking about the laziness of iterators in general is not enough for this specific case IMO. I think it makes sense to tell people how to use this as a drain-like API.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drain is an exception and we deliberately renamed it from DrainFilter to ExtractIf to avoid that association.

I guess you could add the general "iterators are lazy" statement and follow up with a "use retain or for_each(drop)" after that.

Generally we don't want to encourage for_each(drop) too much because it can indicate misuse such as iter.inspect(side_effect).for_each(drop) instead of iter.for_each(side_effect). But in this case it's a legitimate use, due to lack of better alternatives.

When we have a better alternative we can remove the for_each part of the hint.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the wording:

    #[must_use = "this iterator is lazy and does nothing unless consumed; \
        use `retain` or `extract_if().for_each(drop)` to remove and discard elements"]

I went for "this iterator" to make it more clear that this applies to extract_if despite potentially conflicting expectations raised by drain. (I also considered something like "the iterator returned by extract_if" but found that too wordy.)

@RalfJung RalfJung force-pushed the extract_if branch 3 times, most recently from 59d5167 to 0604669 Compare November 16, 2025 13:45
/// ```
#[stable(feature = "btree_extract_if", since = "1.91.0")]
#[must_use = "this iterator is lazy and does nothing unless consumed; \
use `retain` or `extract_if().for_each(drop)` to remove and discard elements"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remind people that retain needs the predicate to be negated?

Alternatively we could only mention the for_each variant here. We do still mention retain in the docs for people that have a closer look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must_use hints seem to be terse in general. I assume this is to not bloat diagnostics, so let's keep it this way.

Comment on lines 691 to 693
#[must_use = "this iterator is lazy and does nothing unless consumed; \
use `extract_if().for_each(drop)` to remove and discard elements"]
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functions without range arguments should only point to retain.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, I forgot the Hash* collections have those

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW personally I would probably still use extract_if in situations where the negation enforced by retain is awkward... in most of these cases, I want to characterize the elements to be removed, and then extract_if(...).for_each(drop) might beat retain(with-negation).

@hanna-kruppe
Copy link
Contributor

The ExtractIf iterator types are already marked as #[must_use] (except for hash_set::ExtractIf, which seems like a mistake). So how about leaving the methods as-is and moving the more specific messages to the respective return type's #[must_use]?

@RalfJung
Copy link
Member Author

The ExtractIf iterator types are already marked as #[must_use] (except for hash_set::ExtractIf, which seems like a mistake). So how about leaving the methods as-is and moving the more specific messages to the respective return type's #[must_use]?

Good point! I did that.

@the8472
Copy link
Member

the8472 commented Nov 16, 2025

@bors r+ rollup

@bors
Copy link
Collaborator

bors commented Nov 16, 2025

📌 Commit fc07052 has been approved by the8472

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 16, 2025
bors added a commit that referenced this pull request Nov 16, 2025
Rollup of 7 pull requests

Successful merges:

 - #148703 (Use `overflow_checks` intrinsic so `IterRangeFrom` yields MAX before panicking in debug)
 - #148881 (use `cfg_select!` to pick assembly in codegen test)
 - #148911 (Make flags from `*FLAGS*` (such as `RUSTFLAGS`) env. vars. have precedence over flags set by bootstrap)
 - #148914 (fix incorrect import in `std_detect` on `aarch64-unknown-openbsd`)
 - #148971 (Document Error::{new,other} as to be avoided in pre_exec)
 - #148983 (Use rustc target metadata for build-manifest target lists)
 - #148995 (add must_use to extract_if methods)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 046e090 into rust-lang:main Nov 16, 2025
11 checks passed
rust-timer added a commit that referenced this pull request Nov 16, 2025
Rollup merge of #148995 - RalfJung:extract_if, r=the8472

add must_use to extract_if methods

Also, mention the `.for_each(drop)` pattern in the documentation. One can't always use `retain` with a negated predicate as that does not have a range argument.

r? `@the8472`
@rustbot rustbot added this to the 1.93.0 milestone Nov 16, 2025
@jhpratt
Copy link
Member

jhpratt commented Nov 17, 2025

still in queue

@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Nov 17, 2025
Muscraft pushed a commit to Muscraft/rust that referenced this pull request Nov 17, 2025
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#148703 (Use `overflow_checks` intrinsic so `IterRangeFrom` yields MAX before panicking in debug)
 - rust-lang#148881 (use `cfg_select!` to pick assembly in codegen test)
 - rust-lang#148911 (Make flags from `*FLAGS*` (such as `RUSTFLAGS`) env. vars. have precedence over flags set by bootstrap)
 - rust-lang#148914 (fix incorrect import in `std_detect` on `aarch64-unknown-openbsd`)
 - rust-lang#148971 (Document Error::{new,other} as to be avoided in pre_exec)
 - rust-lang#148983 (Use rustc target metadata for build-manifest target lists)
 - rust-lang#148995 (add must_use to extract_if methods)

r? `@ghost`
`@rustbot` modify labels: rollup
@RalfJung RalfJung deleted the extract_if branch November 17, 2025 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants